package com.team.engine.basedao;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.List;

import javax.management.RuntimeErrorException;

import org.hibernate.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.orm.hibernate3.HibernateCallback;

import com.team.engine.common.datasources.DataSourceAdapter;
import com.team.engine.util.SubPage;
import com.team.engine.util.SubPageOperate;

/**
 * 基本的增删改查操作类，操作全部是Hibernate实现
 * @author MengLH
 * @data 2010-8-24
 * @param <T> 表实体类
 * @param <ID> 表Id字段类型
 */
public abstract class BaseDaoOperate<T extends BaseEntity, ID> extends DataSourceAdapter implements QueryDaoable<T, ID>,
		UpdateDaoable<T, ID> {
	
	protected final Logger log = LoggerFactory.getLogger(BaseDaoOperate.class);
	
	/**
	 * 表实体类
	 */
	protected Class<T> clazz;
	
	/**
	 * 表实体类名
	 */
	protected String className;
	
	/**
	 * 表实体类Id字段名
	 */
	protected String idName;
	
//	/**
//	 * 表实体类Id字段的Field实例
//	 */
//	protected Field idField;
	
	public SubPage<T> selectAll(int pageNum) {
		SubPageOperate<T> sub = new SubPageOperate<T>(String.valueOf(pageNum), String.valueOf(this.selectCount()));
		return sub.selectSubData(this.getSession().createQuery("from "+className));
	}

	public T selectById(ID id) {
		return (T) this.getHibernateTemplate().get(clazz, (Serializable) id);
	}

	public Long selectCount() {
		Session session = this.getSession();
		long n = (Long) session.createQuery("select count(t."+idName+") from "+className+" t").uniqueResult();
		return n;
	}

	public Long selectMax() {
		Long l = (Long) this.getSession().createQuery("select max(t."+idName+") from "+className+" t").uniqueResult();
		return l;
	}

	public int delete(T t) {
		this.getHibernateTemplate().delete(t);
		return 0;
	}

	public int deleteById(ID id) {
		T newInstance = null;
		try {
			newInstance = clazz.newInstance();
			Field f = newInstance.getClass().getDeclaredField(idName);
			f.setAccessible(true);
			String typeName = f.getType().getSimpleName();
			if(typeName.equals("String"))
				f.set(newInstance, id);
			if(typeName.equals("int") || typeName.equals("Integer"))
				f.set(newInstance, id);
			if(typeName.equals("long") || typeName.equals("Long"))
				f.set(newInstance, id);
			
		} catch (InstantiationException e) {
			throw new RuntimeException(e);
		} catch (IllegalAccessException e) {
			throw new RuntimeException(e);
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			throw new RuntimeException(e);
		}
		
		this.getHibernateTemplate().delete(className, newInstance);
		return 0;
	}

	public int deleteByList(List<T> list) {
		this.getHibernateTemplate().deleteAll(list);
		return 0;
	}
	
	public ID insert(T t) {
		Serializable save = this.getHibernateTemplate().save(t);
		Object id = null;
		try {
			Field f = t.getClass().getDeclaredField(idName);
			f.setAccessible(true);
			id = f.get(t);
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			throw new RuntimeException(e);
		} catch (NoSuchFieldException e) {
			throw new RuntimeException(e);
		}
		
		return (ID) id;
	}
	
//	public ID insertSelective(T t, String...str){
//		Serializable save = this.getHibernateTemplate().save(t);
//		return (ID) id;
//	} 

	public int insertBatch(final List<T> list) {
		Integer n = (Integer) this.getHibernateTemplate().execute(new HibernateCallback() {

            public Object doInHibernate(Session session) {
            	for(int i=0;i<list.size();i++){
            		session.save(list.get(i));
            		if(i % hibernateJdbcBatchSize == 0){
            			session.flush();
            			session.clear();
            		}
            	}
                return new Integer(0);
            }
        });
		 return n;
	}

	public int updateBatchById(List<T> list) {
		return 0;
	}

	public int updateById(T t) {
		return 0;
	}
	
}
